package edu.upenn.seas.peerreview.pr

import edu.upenn.seas.peerreview.{Id, Sink, Source}
import edu.upenn.seas.peerreview.pr.PRMessages._

class PRSwitching (myId:Id, transport:Sink.T, f:Source.Factory) extends Source.T {
 val crypto: Crypto = new Crypto()
 val log: Log = new Log()
 var myUI : Id = null
 var okToReleaseLog : Boolean = false
 val startTime = System.currentTimeMillis
 val debug=edu.upenn.seas.peerreview.Debug.debug("log")(_)
 // the pipe mySM uses to send messages
 val sendPipe = new Sink.T {
   def apply(to: Id, msg: Message) = {
     msg match{
       case msg:OKToReleaseLog => 
	 okToReleaseLog = true
       case PleaseAudit(i:Id) =>
	 transport(i, PleaseSendYourLog())
       case _ => {
	 val id : SeqNum = log.addSent(to, msg)
	 if(to == Id.coordinatorId)
	   transport(to, msg)
	 else
           transport(to, PR_SEND(msg, id))
       }
     }   
   }
 }
 
  val mySM = f(myId, sendPipe)
  
  // the write method for *this* which is the pipe Transport sends messages
  // to the SM through


  def apply(from:Id, msg:Message) = {
    msg match {
      case PleaseSendYourLog() =>
        if (okToReleaseLog) {
	  val logQueue = log.log
	  val x = log.log.dequeue
	  log.log.enqueue(x)
          transport(from, HereIsMyLog(log))
	}
        else {
          transport(from, HereIsMyLog(null))
          debug("Log requested before my UI said it was OK!")
	}
      case HereIsMyLog(null) =>
	debug("Null log received.")
      case HereIsMyLog(l:Log) =>
	debug("Log received from " + from)
        mySM(myId, AuditResult(l.audit(f(from, _))))
      case PR_SEND(msg: Message, idSent: SeqNum) => {
        val idRec : SeqNum = log.addRecv(from, msg, idSent)
        mySM(from,msg)
      }
      case _ => 
        // treat time elapsed since this node created as sequence number in "log"
        val recvValue=log.addRecv(from, msg, (System.currentTimeMillis-startTime).toInt)
        mySM(from, msg)
    }
  }
}
